home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / unix / mp14tar.z / mp14tar / mpack / macfile.c < prev    next >
C/C++ Source or Header  |  1994-06-01  |  8KB  |  256 lines

  1. /* macfile.c -- simple applesingle/appledouble encoding/decoding routines
  2.  *
  3.  * (C) Copyright 1994 by Christopher J. Newman
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of Christopher J. Newman not be used in
  11.  * advertising or publicity pertaining to distribution of the software without
  12.  * specific, written prior permission.  Christopher J. Newman makes no
  13.  * representations about the suitability of this software for any purpose.  It
  14.  * is provided "as is" without express or implied warranty.
  15.  *
  16.  * CHRISTOPHER J. NEWMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  17.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
  18.  * SHALL CHRISTOPHER J. NEWMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  19.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  20.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  21.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  22.  * OF THIS SOFTWARE.
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <memory.h>
  27. #include "macnapp.h"    /* for NAfilterProc */
  28. #include "macmpack.h"   /* for copy_buf */
  29.  
  30. /* applefile definitions used */
  31. #define APPLESINGLE_MAGIC 0x00051600L
  32. #define APPLEDOUBLE_MAGIC 0x00051607L
  33. #define VERSION 0x00020000
  34. #define ENT_DFORK   1
  35. #define ENT_RFORK   2
  36. #define ENT_NAME    3
  37. #define ENT_COMMENT 4
  38. #define ENT_DATES   8
  39. #define ENT_FINFO   9
  40. #define CONVERT_TIME 1265437696L
  41.  
  42. /* applefile structures */
  43. typedef struct ap_header {
  44.     long magic;
  45.     long version;
  46.     char fill[16];
  47.     short entries;
  48. } ap_header;
  49. typedef struct ap_entry {
  50.     unsigned long id;
  51.     unsigned long offset;
  52.     unsigned long length;
  53. } ap_entry;
  54. typedef struct ap_dates {
  55.     long create, modify, backup, access;
  56. } ap_dates;
  57.  
  58. /* default number of entries */
  59. #define NUM_ENTRIES 6
  60.  
  61. /* Generate an applefile
  62.  *  outfile -- output file
  63.  *  fpb -- hierarchical file parameter block
  64.  *  rfork, dfork -- resource & data forks
  65.  * returns -1 on failure, 0 on success
  66.  *
  67.  * closes dfork & rfork, but not outputfile
  68.  */
  69. int encode_applefile(FILE *outfile, HFileInfo *fpb, FILE *rfork, FILE *dfork)
  70. {
  71.     ap_header head;
  72.     ap_entry entries[NUM_ENTRIES];
  73.     ap_dates dates;
  74.     short i, count;
  75.     DateTimeRec cur_time;
  76.     unsigned long cur_secs;
  77.     
  78.     /* make sure things look OK */
  79.     if (!rfork || !outfile) {
  80.         if (rfork) fclose(rfork);
  81.         if (dfork) fclose(dfork);
  82.         if (outfile) fclose(outfile);
  83.         return (-1);
  84.     }
  85.     
  86.     /* write header */
  87.     head.magic = dfork ? APPLESINGLE_MAGIC : APPLEDOUBLE_MAGIC;
  88.     head.version = VERSION;
  89.     memset(head.fill, '\0', sizeof (head.fill));
  90.     head.entries = NUM_ENTRIES - (dfork ? 0 : 1);
  91.     fwrite((char *) &head, sizeof (head), 1, outfile);
  92.     
  93.     /* write entry descriptors */
  94.     entries[0].offset = sizeof (head) + sizeof (ap_entry) * head.entries;
  95.     entries[0].id = ENT_NAME;
  96.     entries[0].length = *fpb->ioNamePtr;
  97.     entries[1].id = ENT_FINFO;
  98.     entries[1].length = sizeof (FInfo) + sizeof (FXInfo);
  99.     entries[2].id = ENT_DATES;
  100.     entries[2].length = sizeof (ap_dates);
  101.     entries[3].id = ENT_COMMENT;
  102.     entries[3].length = 0;
  103.     entries[4].id = ENT_RFORK;
  104.     entries[4].length = fpb->ioFlRLgLen;
  105.     entries[5].id = ENT_DFORK;
  106.     entries[5].length = fpb->ioFlLgLen;
  107.     for (i = 1; i < NUM_ENTRIES; ++i) {
  108.         entries[i].offset = entries[i-1].offset + entries[i-1].length;
  109.     }
  110.     fwrite((char *) entries, sizeof (ap_entry), head.entries, outfile);
  111.     
  112.     /* write name */
  113.     fwrite((char *) fpb->ioNamePtr + 1, *fpb->ioNamePtr, 1, outfile);
  114.     /* write finder info */
  115.     fwrite((char *) &fpb->ioFlFndrInfo, sizeof (FInfo), 1, outfile);
  116.     fwrite((char *) &fpb->ioFlXFndrInfo, sizeof (FXInfo), 1, outfile);
  117.     /* write dates */
  118.     GetTime(&cur_time);
  119.     Date2Secs(&cur_time, &cur_secs);
  120.     dates.create = fpb->ioFlCrDat + CONVERT_TIME;
  121.     dates.modify = fpb->ioFlMdDat + CONVERT_TIME;
  122.     dates.backup = fpb->ioFlBkDat + CONVERT_TIME;
  123.     dates.access = cur_secs + CONVERT_TIME;
  124.     fwrite((char *) &dates, sizeof (ap_dates), 1, outfile);
  125.     /*XXX: need to write comment */
  126.     /* write resource fork */
  127.     while ((count = fread(copy_buf, sizeof (char), sizeof (copy_buf), rfork)) > 0) {
  128.         fwrite(copy_buf, sizeof (char), count, outfile);
  129.     }
  130.     fclose(rfork);
  131.     /* write data fork */
  132.     if (dfork) {
  133.         while ((count = fread(copy_buf, sizeof (char), sizeof (copy_buf), dfork)) > 0) {
  134.             fwrite(copy_buf, sizeof (char), count, outfile);
  135.         }
  136.         fclose(dfork);
  137.     }
  138.     
  139.     return (0);
  140. }
  141.  
  142. /* decode an applefile
  143.  *  infile -- input file
  144.  *  fspec  -- file spec of saved file
  145.  * returns -1 on failure, 0 on success
  146.  */
  147. int decode_applefile(FILE *infile, FSSpec *fspec)
  148. {
  149.     ap_header head;
  150.     ap_entry entries[NUM_ENTRIES + 1];
  151.     ap_dates dates;
  152.     Point where;
  153.     SFReply reply;
  154.     int i, j;
  155.     short refnum;
  156.     long count;
  157.     OSErr err;
  158.     HFileInfo *fpb;
  159.     CInfoPBRec cipbr;
  160.     
  161.     /* read & verify header */
  162.     fread((char *) &head, sizeof (head), 1, infile);
  163.     if (head.magic != APPLESINGLE_MAGIC && head.magic != APPLEDOUBLE_MAGIC) {
  164.         return (-1);
  165.     }
  166.     if (head.version != VERSION) {
  167.         return (-1);
  168.     }
  169.     
  170.     /* read entries */
  171.     for (i = j = 0; i < head.entries; ++i) {
  172.         fread((char *) (entries + j), sizeof (ap_entry), 1, infile);
  173.         if (j < NUM_ENTRIES) switch (entries[j].id) {
  174.             case ENT_NAME:
  175.             case ENT_FINFO:
  176.             case ENT_DATES:
  177.             case ENT_COMMENT:
  178.             case ENT_RFORK:
  179.             case ENT_DFORK:
  180.                 ++j;
  181.                 break;
  182.         }
  183.     }
  184.     
  185.     /* read name */
  186.     for (i = 0; i < j && entries[i].id != ENT_NAME; ++i);
  187.     if (i == j) return (-1);
  188.     fseek(infile, entries[i].offset, SEEK_SET);
  189.     if (entries[i].length > 63) entries[i].length = 63;
  190.     *fspec->name = fread((char *) fspec->name + 1, sizeof (char), entries[i].length, infile);
  191.     where.h = where.v = 0;
  192.     SFPutFile(where, "\pSave decoded file as:", fspec->name, NULL, &reply);
  193.     if (!reply.good) return (-1);
  194.     BlockMove(reply.fName, fspec->name, sizeof (fspec->name));
  195.     fspec->vRefNum = reply.vRefNum;
  196.     fspec->parID = 0;
  197.  
  198.     /* create & get info for file */
  199.     if (Create(fspec->name, fspec->vRefNum, '????', '????') != noErr) return (-1);
  200.     fpb = (HFileInfo *) &cipbr;
  201.     fpb->ioVRefNum = fspec->vRefNum;
  202.     fpb->ioNamePtr = fspec->name;
  203.     fpb->ioDirID = 0;
  204.     fpb->ioFDirIndex = 0;
  205.     PBGetCatInfoSync(&cipbr);
  206.     
  207.     /* get finder info */
  208.     for (i = 0; i < j && entries[i].id != ENT_FINFO; ++i);
  209.     if (i < j) {
  210.         fseek(infile, entries[i].offset, SEEK_SET);
  211.         fread((char *) &fpb->ioFlFndrInfo, sizeof (FInfo), 1, infile);
  212.         fread((char *) &fpb->ioFlXFndrInfo, sizeof (FXInfo), 1, infile);
  213.         fpb->ioFlFndrInfo.fdFlags &= 0xf800; /* clear flags maintained by finder */
  214.     }
  215.     
  216.     /* get file date info */
  217.     for (i = 0; i < j && entries[i].id != ENT_DATES; ++i);
  218.     if (i < j) {
  219.         fseek(infile, entries[i].offset, SEEK_SET);
  220.         fread((char *) &dates, sizeof (dates), 1, infile);
  221.         fpb->ioFlCrDat = dates.create - CONVERT_TIME;
  222.         fpb->ioFlMdDat = dates.modify - CONVERT_TIME;
  223.         fpb->ioFlBkDat = dates.backup - CONVERT_TIME;
  224.     }
  225.     
  226.     /* update info */
  227.     fpb->ioDirID = 0;
  228.     PBSetCatInfo(&cipbr, FALSE);
  229.     
  230.     /* do resource/data forks */
  231.     for (i = 0; i < j; ++i) {
  232.         if (entries[i].id == ENT_RFORK || entries[i].id == ENT_DFORK) {
  233.             fseek(infile, entries[i].offset, SEEK_SET);
  234.             if (entries[i].id == ENT_DFORK) {
  235.                 err = HOpen(fspec->vRefNum, fspec->parID, fspec->name, 2, &refnum);
  236.             } else {
  237.                 err = HOpenRF(fspec->vRefNum, fspec->parID, fspec->name, 2, &refnum);
  238.             }
  239.             if (err != noErr) {
  240.                 FSDelete(fspec->name, fspec->vRefNum);
  241.                 return (-1);
  242.             }
  243.             while (entries[i].length > sizeof (copy_buf)) {
  244.                 count = fread(copy_buf, sizeof (char), sizeof (copy_buf), infile);
  245.                 entries[i].length -= count;
  246.                 FSWrite(refnum, &count, (Ptr) copy_buf);
  247.             }
  248.             count = fread(copy_buf, sizeof (char), entries[i].length, infile);
  249.             FSWrite(refnum, &count, (Ptr) copy_buf);
  250.             FSClose(refnum);
  251.         }
  252.     }
  253.     
  254.     return (0);
  255. }
  256.